﻿using System;
using System.Collections.Generic;
using System.Text;

using AIFSContentManagementSystem.DomainObjects;

namespace AIFSContentManagementSystem.CriteriaManagement
{
    public class CriteriaAsserter : ICriteriaAsserter
    {
        public bool IsMatch(Criteria RequestCriterion, List<Criteria> OrCriteria, List<Criteria> expectedCriteria)
        {
            if (expectedCriteria == null || expectedCriteria.Count == 0)
                throw new ArgumentNullException("expectedCriteria can not be null or empty");

            bool assertionResult = IsMatch(RequestCriterion, expectedCriteria);

            if (assertionResult)
                return true;

            if (OrCriteria == null || OrCriteria.Count == 0) //if no or condition specified
                return assertionResult;

            //If the first criteria did not match go through all of them
            foreach (Criteria factCriterion in OrCriteria)
            {
                assertionResult = IsMatch(factCriterion, expectedCriteria);

                if (assertionResult)
                    break;
            }

            return assertionResult;
        }

        private bool IsMatch(Criteria factCriterion, List<Criteria> expectedCriteria)
        {
            bool assertionResult = false;
            foreach (Criteria expectedCriterion in expectedCriteria)
            {
                assertionResult = IsMatch(factCriterion, expectedCriterion);
                if (assertionResult)
                    break;
            }

            return assertionResult;
        }

        /// <summary>
        /// This method asserts the 2 series of criteria. All comparisions are AND-ed within this method
        /// </summary>
        private bool IsMatch(Criteria factCriterion, Criteria expectedCriterion)
        {
            List<CriterionExpression> originalExpList = factCriterion.CriteriaExpression;
            List<CriterionExpression> expectedExpList = expectedCriterion.CriteriaExpression;


            int countMatches = 0;
            foreach (CriterionExpression expectedExp in expectedExpList)
            {
                foreach (CriterionExpression originalExp in originalExpList)
                {
                    if (originalExp.Match(expectedExp))
                    {
                        countMatches = countMatches + 1;
                        break; //DO NOT GO FURTHER FOR THIS COMBINATION
                    }
                }
            }

            //All expected criteria matched or not
            return (countMatches == expectedExpList.Count);
        }
    }
}
